package com.hzjq.core.impl

import android.text.TextUtils
import com.hzjq.core.ErrorCode
import com.hzjq.core.bean.*
import com.hzjq.core.callback.Callback
import com.hzjq.core.callback.ProgressCallback
import com.hzjq.core.loader.OnQuickRegisterLoader
import com.hzjq.core.util.ErrorChecker
import com.hzjq.core.work.Works
import com.hzjq.core.worker.*
import io.reactivex.functions.Consumer

class QuickRegisterImpl : OnQuickRegisterLoader {

    private var underWorks: Works? = null
    private var authWorks: Works? = null
    private var maxDelay = -1L
    private var readCaps = arrayListOf<ErrorCapEntity>()

    override fun onQuickRegister(
        caps: MutableList<CapEntity>,
        maxDelay: Long,
        callback: ProgressCallback<CapProgressEntity>,
        errorCallback: Consumer<ErrorReadCapEntity>
    ) {
        CheckerImpl().setCallback(Consumer {
            if (it) {
                this.maxDelay = maxDelay
                readCaps.clear()
                cancel()
                doRegisterCaps(caps, callback, errorCallback)
            } else {
                callback.onError(ErrorCode.getErrorResult(103))
            }
        }).start()
    }

    override fun exitQuickRegister(callback: Callback<Boolean>) {
        CheckerImpl().setCallback(Consumer {
            if (it) {
                cancel()
                BackWork(callback).doWork()
            } else {
                callback.onError(ErrorCode.getErrorResult(103))
            }
        }).start()
    }

    private fun doRegisterCaps(
        caps: MutableList<CapEntity>,
        callback: ProgressCallback<CapProgressEntity>,
        underErrorCallback: Consumer<ErrorReadCapEntity>
    ) {

        val authCall = object : ProgressCallback<CapProgressEntity> {
            override fun onResult(t: CapProgressEntity) {
                callback.onResult(t)
            }

            override fun onRetryCountChanged(retryCount: Int, action: String) {
                callback.onRetryCountChanged(retryCount, action)
            }

            override fun onError(errorCode: ErrorResult) {
                callback.onError(errorCode)
            }

            override fun onProgressChanged(progress: Int, total: Int, action: String) {
                callback.onProgressChanged(50 + progress / 2, 100, action)
            }

        }

        val authErrorCall = object : ProgressCallback<ErrorReadCapEntity> {
            override fun onResult(t: ErrorReadCapEntity) {
                underErrorCallback.accept(t)
            }

            override fun onRetryCountChanged(retryCount: Int, action: String) {
                callback.onRetryCountChanged(retryCount, action)
            }

            override fun onError(errorCode: ErrorResult) {
                callback.onError(errorCode)
            }

            override fun onProgressChanged(progress: Int, total: Int, action: String) {
                callback.onProgressChanged(progress, 100, action)
            }

        }

        val underCall = object : ProgressCallback<ErrorReadCapEntity> {
            override fun onResult(t: ErrorReadCapEntity) {
                if (t.caps[t.caps.size - 1].isScanEnd) {
                    if (t.errors.isEmpty()) {
                        authWorks = Works.Builder.newBuilder()
                            .addWork(InnerAuthModeWork(authCall))
                            .addWork(AuthQueryWork(authCall, authErrorCall))
                            .addWork(InnerCheckTimeWork(authCall))
                            .addWork(CheckTimeQueryWork(maxDelay, authCall, authErrorCall))
                            .addWork(ElectricVoltageWork(callback))
                            .build()
                            .queue()
                    } else {
                        underErrorCallback.accept(t)
                    }
                }
            }

            override fun onRetryCountChanged(retryCount: Int, action: String) {
                callback.onRetryCountChanged(retryCount, action)
            }

            override fun onError(errorCode: ErrorResult) {
                callback.onError(errorCode)
            }

            override fun onProgressChanged(progress: Int, total: Int, action: String) {
                callback.onProgressChanged(progress / 2, 100, action)
            }

        }

        val capCallback = object : ProgressCallback<MutableList<CapEntity>> {
            override fun onResult(t: MutableList<CapEntity>) {
                t.forEach {
                    val ecp = ErrorChecker.checkMeetMiss(it)
                    if (ecp != null && !contains(ecp)) {
                        readCaps.add(ecp)
                    }
                }
                if (t[t.size - 1].isScanEnd) {
                    val mErrorReadCapEntity = ErrorReadCapEntity()
                    mErrorReadCapEntity.errors.addAll(readCaps)
                    underCall.onResult(mErrorReadCapEntity)
                }
            }

            override fun onRetryCountChanged(retryCount: Int, action: String) {
                callback.onRetryCountChanged(retryCount, action)
            }

            override fun onError(errorCode: ErrorResult) {
                callback.onError(errorCode)
            }

            override fun onProgressChanged(progress: Int, total: Int, action: String) {
                callback.onProgressChanged(progress, total, action)
            }
        }

        underWorks = Works.Builder.newBuilder()
            .addWork(CheckCapPassWordWork(caps, underCall))
            .addWork(ClearChipStateWork(caps, capCallback))
            .addWork(UnderCapWork(underCall))
            .addWork(UnderInnerScanModeWork(caps, capCallback))
            .addWork(UnderScanShipWork(callback, underCall, capCallback))
            .build()
            .queue()
    }


    fun contains(cap: ErrorCapEntity): Boolean {
        if (readCaps.isNotEmpty()) {
            readCaps.forEach {
                if (TextUtils.equals(cap.cap!!.uid, it.cap!!.uid)) {
                    return true
                }
            }
        }
        return false
    }

    override fun cancel() {
        underWorks?.onDestroy()
        authWorks?.onDestroy()
    }
}